package com.server.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.server.liad.api.system.remote.RemoteSystemService;
import com.server.model.all.system.dto.AddLogOperationDto;
import com.server.model.all.user.bo.LoginBo;
import com.server.model.all.user.bo.SmsLoginBo;
import com.server.common.code.utils.UserUtils;
import com.server.model.all.enums.sms.SmsTypeEnum;
import com.server.common.code.utils.BeanUtils;
import com.server.common.code.error.BusinessException;
import com.server.common.code.utils.OptionalUtils;
import com.server.common.redis.RedisService;
import com.server.common.redis.service.RedisSmsService;
import com.server.common.redis.service.verify.RedisLoginVerifyService;
import com.server.common.redis.token.TokenServices;
import com.server.common.redis.service.RedisUserBlackListService;
import com.server.common.code.vo.LoginVo;
import com.server.model.all.enums.YesNoEnum;
import com.server.model.all.user.bo.ForgetPasswordBo;
import com.server.model.all.user.bo.RegisterUserBo;
import com.server.model.all.user.entity.UserEntity;
import com.server.common.security.code.SecurityUtils;
import com.server.user.service.RoleMenuService;
import com.server.user.service.UserRoleService;
import com.server.user.service.UserService;
import com.server.model.all.user.vo.UserInfoVo;
import com.server.user.mapper.UserMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Optional;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, UserEntity> implements UserService {

    @Resource
    private UserMapper userMapper;

    @Resource
    private RoleMenuService roleMenuService;

    @Resource
    private UserRoleService userRoleService;

    @Resource
    private TokenServices tokenServices;

    @Resource
    private RemoteSystemService remoteSystemService;

    @Resource
    private RedisService redisService;

    @Resource
    private RedisLoginVerifyService loginVerifyService;

    @Resource
    private RedisSmsService redisSmsService;

    @Resource
    private RedisUserBlackListService redisUserBlackListService;

    /**
     * 登录
     * @author LXC
     * @date 2022/4/28 20:28
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public LoginVo login(LoginBo loginBo) {
        AddLogOperationDto addLogOperationDto = new AddLogOperationDto();
        addLogOperationDto.setMethod("1");
        remoteSystemService.addLogOperation(addLogOperationDto);

        UserEntity userEntity = BeanUtils.copyProperties(loginBo,UserEntity.class);

        //判断验证码
        loginVerifyService.checkLoginVerifyCode(loginBo.getTextCode(),loginBo.getTextValue());

        //获取用户
        UserEntity userEntityNew = userMapper.selectOne(new LambdaQueryWrapper<>(userEntity).last("limit 1"));

        //校验登录
        checkLogin(userEntityNew);

        //登录
        return login(userEntityNew);
    }

    @Override
    public LoginVo smsLogin(SmsLoginBo smsLoginBo) {
        UserEntity userEntity = BeanUtils.copyProperties(smsLoginBo,UserEntity.class);

        //获取用户
        UserEntity userEntityNew = userMapper.selectOne(new LambdaQueryWrapper<>(userEntity).last("limit 1"));

        //校验登录
        checkLogin(userEntityNew);

        //判断短信验证码
        redisSmsService.checkSmsCode(SmsTypeEnum.LOGIN.getSmsTypeRedisKey(), smsLoginBo.getMobile(), smsLoginBo.getSmsCode());

        //登录
        return login(userEntityNew);
    }

    @Override
    public UserInfoVo getUserInfo(Long userId) {

        UserEntity userEntity = userMapper.selectOne(new LambdaQueryWrapper<UserEntity>()
                .eq(UserEntity::getUserId, userId)
                .eq(UserEntity::getDelFlag, YesNoEnum.NO.getCode())
                .eq(UserEntity::getStatus, YesNoEnum.YES.getCode())
        );
        return BeanUtils.copyProperties(userEntity, UserInfoVo.class);
    }

    @Override
    public Integer register(RegisterUserBo registerUserBo) {
        UserEntity userEntity = BeanUtils.copyProperties(registerUserBo, UserEntity.class);

        //校验用户是否可以注册
        checkUserRegister(userEntity);

        //判断短信验证码
       redisSmsService.checkSmsCode(SmsTypeEnum.REGISTER.getSmsTypeRedisKey(),
                registerUserBo.getMobile(), registerUserBo.getSmsCode());

        return userMapper.insert(userEntity);
    }

    /**
     * 通用登录实现
     * @author LXC
     * @date 2022/6/20 23:23
     */
    @Override
    public LoginVo login(UserEntity userEntity){
        LoginVo loginVo = BeanUtils.copyProperties(userEntity, LoginVo.class);

        //获取角色集合
        List<Long> roles = userRoleService.getUserRoleByUserId(loginVo.getUserId());
        loginVo.setRoleId(roles);

        //获取权限字符集合
        List<String> paths = roleMenuService.findPathsByRoleId(roles);
        loginVo.setPreAuths(paths);

        //获取ip
        loginVo.setIpAddress(SecurityUtils.getIpAddress());

        return loginVo;
    }

    /**
     * 判断用户是否能注册
     * @author LXC
     * @date 2022/6/20 23:26
     */
    @Override
    public void checkUserRegister(UserEntity checkUserEntity){
        UserEntity queryUserEntity = getOne(new LambdaQueryWrapper<UserEntity>()
                .eq(UserEntity::getUserName, checkUserEntity.getUserName())
                .or()
                .eq(UserEntity::getMobile, checkUserEntity.getMobile())
                .or()
                .eq(UserEntity::getEmail, checkUserEntity.getEmail())
        );

        UserEntity queryUserEntityNew = Optional.ofNullable(queryUserEntity)
                .orElse(new UserEntity());

        if(checkUserEntity.getUserName().equals(queryUserEntityNew.getUserName())){
            throw new BusinessException("用户名已存在");
        }

        if(checkUserEntity.getMobile().equals(queryUserEntityNew.getMobile())){
            throw new BusinessException("手机号已存在");
        }

        if(checkUserEntity.getEmail().equals(queryUserEntityNew.getEmail())){
            throw new BusinessException("邮箱地址已存在");
        }

    }

    @Override
    public int forgetPassword(ForgetPasswordBo forgetPasswordBo) {
        UserEntity userEntity = getOne(new LambdaQueryWrapper<UserEntity>()
                .eq(UserEntity::getUserName, forgetPasswordBo.getUserName())
                .or()
                .eq(UserEntity::getEmail, forgetPasswordBo.getEmail())
                .or()
                .eq(UserEntity::getMobile, forgetPasswordBo.getMobile())
        );

        OptionalUtils.ofEmpty(userEntity).orElseThrow(()->new BusinessException("用户名|邮箱|手机号输入错误"));

        //判断短信验证码
        redisSmsService.checkSmsCode(SmsTypeEnum.FORGET_PASSWORD.getSmsTypeRedisKey(),
                forgetPasswordBo.getMobile(), forgetPasswordBo.getSmsCode());

        //更新密码
        userEntity.setPassWord(forgetPasswordBo.getPassWord());
        updateById(userEntity);

        return 1;
    }

    /**
     * 校验登录
     * @author LXC
     * @date 2022/11/13 14:34
     */
    public void checkLogin(UserEntity userEntity){
        OptionalUtils.ofEmpty(userEntity).orElseThrow(()->new BusinessException("用户名或者密码不存在!"));

        if(UserUtils.haveDelete(userEntity.getDelFlag())){
            throw new BusinessException("用户已被删除!");
        }

        if(UserUtils.haveDisable(userEntity.getStatus())){
            throw new BusinessException("用户已被禁用!");
        }

        //用户-黑名单
        if(Boolean.TRUE.equals(redisUserBlackListService.hasBlackUserId(userEntity.getUserId()))){
            throw new BusinessException("404 NOT FIND!");
        }
    }


}
